package pers.vic.boot.security.data.interceptor;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pers.vic.boot.security.data.enums.RowDataHandlerType;
import pers.vic.boot.security.data.model.DataRowAuthColumn;
import pers.vic.boot.security.data.model.DataRowAuthModel;

import java.sql.Connection;
import java.util.Properties;
import java.util.Set;


/**
 * @description: 权限拦截器 ,  拦截StatementHandler对象的prepare ,然后重写SQL 加入where条件过滤;
 * 	使用方式: RowDataHelper.start
 * @author: Vic.xu
 * @date: 2020年2月11日 下午1:41:39
 */
@Intercepts({
        @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class RowDataHelper extends BaseAuthorityMethod implements Interceptor {

    private static final Logger LOGGER = LoggerFactory.getLogger(RowDataHelper.class);

    /**
     * 1、获取到拦截到的StatementHandler对象； 2、封装StatementHandler对象；
     * 3、执行Invocation对应的数据库操作方法；
     */
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler target = (StatementHandler) invocation.getTarget();
        handler(target);
        return invocation.proceed();
    }

    /**
     * 返回目标对象的代理对象
     */
    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }


    /**
     * 数据权限 处理 SQL追加
     *
     * @param handler
     */
    public void handler(StatementHandler handler) {
        BoundSql boundSql = handler.getBoundSql();
        String sql = boundSql.getSql();
        DataRowAuthModel authorityData = getLocalAuthorityData();
        if (authorityData == null) {
            return;
        }
        Set<DataRowAuthColumn> columns = authorityData.getFilterColumns();
        if (CollectionUtils.isEmpty(columns)) {
            return;
        }
        for (DataRowAuthColumn column : columns) {
            RowDataHandlerType sqlHandler = column.getType();
            // 处理SQL 追加权限
            sql = sqlHandler.handlerSql(sql, column.getColumn());
        }
        overrideSql(boundSql, sql);
    }

    @Override
    public void setProperties(Properties properties) {
        String dialect = properties.getProperty("dialect");
        LOGGER.info("RowDataHelper for mybatis intercept dialect:{}", dialect);
    }
}
